<?php
class VerificationCode{
	const _ChineseChar = "中文字库我是开发者杨承志验证码数算术乾坎艮震巽离坤兑休生伤杜景死惊国际暑期学校通世傲为";
	private static $type;		//验证码类型
	//0:随机; 1:数字; 2:字母; 3:数字加字母; 4:汉字;
	const _WIDTH = 110;
	const _HEIGHT= 40;
	private static $width;		//图片尺寸,px
	private static $height=40;
	private static $font=array('msyhbd.ttf', 'simkai.ttf');		//字体库(文件名)
	private static $fontChinese=array('msyhbd.ttf', 'simkai.ttf');		//字体库(文件名)
	private static $fontFace ;	//选用的字体
	private static $fontSize=array(20,24);	//字号
	private static $length;		//验证码长度
	private static $imageType;	//图片类型
	private static $image;		//图片句柄
	private static $sessionName = 'VerificationCode';
	public static $code;		//验证码值

	//生成码值
	private static function createCode(){
		switch (self::$type) {
			case 1:
				self::ccNumber();	//生成数字验证码
				break;
			case 2:
				self::ccLetter();	//生成字母验证码
				break;
			case 3:
				self::ccNL();		//生成数字加字母验证码
				break;
			case 4:
				self::ccCC();		//生成汉字验证码
				break;
		}
		$_SESSION[self::$sessionName] = strtoupper(self::$code) ;

		return self::$code;
	}

	private static function ccNumber(){
		for ($i = 0; $i < self::$length; $i++) {
			self::$code .= mt_rand(0, 9);
		}
	}

	private static function ccLetter(){
		$str="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
		for($i=0; $i< self::$length; $i++){
			$num=mt_rand(0,25);
			self::$code .= $str[$num];
		}
	}

	private static function ccNL(){
		// 去掉了 0 1 O l 等
		$str = "23456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
		for ($i = 0; $i < self::$length; $i++) {
			$num=mt_rand(0,31);
			self::$code .= $str[$num];
		}
	}

	private static function ccCC(){
		for ($i = 0; $i < self::$length; $i++) {
			$num=mt_rand(0,mb_strlen(VerificationCode::_ChineseChar, 'UTF-8')-1);
			self::$code .= mb_substr(VerificationCode::_ChineseChar, $num, 1, 'UTF-8');
		}
	}

	//输出图片
	public static function output($type=0, $length=4, $sessionName = 'VerificationCode'){
		self::$length = $length ? $length : 1;
		self::$sessionName = $sessionName;
		self::$type = $type ? $type : mt_rand() % 4 +1;
		

		if (self::$type == 4) {
			self::$fontSize[0] =16;
			self::$fontSize[1] =18;
			self::$fontFace = self::$fontChinese[mt_rand() % count(self::$fontChinese)];
		}
		else{
			self::$fontSize[0] =20;
			self::$fontSize[1] =24;
			self::$fontFace = self::$font[mt_rand() % count(self::$font)];
		}

		self::$width = (int)(24 * self::$length+tan(deg2rad(30))*24);
		//self::$width = 110;
		self::$height = 40;

		if (strlen(self::$code)==0)
			self::createCode();	//生成码值

		self::$image=imagecreatetruecolor(self::$width,self::$height);

		//两种生成模式的图片
		if (self::$type == 4) {
			self::createImage1();
		}
		else{
			if (mt_rand()%2) {
				self::createImage1();
			}
			else
				self::createImage2();
		}

		//加入干扰象素;
		for($i=0; $i<self::$width; $i++){
			$randcolor = ImageColorallocate(self::$image,mt_rand(0,255),mt_rand(0,255),mt_rand(0,255));
			imagesetpixel(self::$image, mt_rand()%self::$width , mt_rand()%self::$height , $randcolor);
		}
		
		header("Content-type: image/png");
		imagepng(self::$image);
		imagedestroy(self::$image);
		
		/*echo self::$type;
		echo ' - ';
		echo self::$code;*/
	}

	private static function createImage1(){
		
		
		$bkcolor=imagecolorallocate(self::$image,mt_rand(100,255),mt_rand(100,255),mt_rand(100,255));
		imagefill(self::$image,0,0,$bkcolor);

		/***********内容*********/
		for($i=0; $i<self::$length; $i++){
			$fontcolor=imagecolorallocate(self::$image,mt_rand(0,120),mt_rand(0,120),mt_rand(0,120)); //这样保证随机出来的颜色较深。
			$x = 20*$i+tan(deg2rad(30))*24;
			$y = mt_rand( 24,  self::$height-sin(deg2rad(30))*24);

			imagettftext(
				self::$image,	//图片句柄
				mt_rand(self::$fontSize[0], self::$fontSize[1]),	//随机字号
				mt_rand(-30,30),	//旋转角度
				$x,			//横坐标
				$y,		//纵坐标
				$fontcolor,			//字体颜色
				dirname(__FILE__). DIRECTORY_SEPARATOR . self::$fontFace,		//字体
				mb_substr(self::$code, $i, 1, 'UTF-8')			//文字内容
			);
		}

		/***添加干扰***/
		for($i=0;$i<10;$i++){
			$fontcolor=imagecolorallocate(self::$image,mt_rand(0,255),mt_rand(0,255),mt_rand(0,255));
			imagearc(self::$image,mt_rand(-10,self::$width),mt_rand(-10,self::$height),mt_rand(30,300),mt_rand(20,200),55,44,$fontcolor);
		}
	}

	private static function createImage2(){
		$image = imagecreatetruecolor(self::$width,self::$height);

		$text_c = ImageColorAllocate($image, mt_rand(0,100),mt_rand(0,100),mt_rand(0,100));
		$tmpC0=mt_rand(100,255);
		$tmpC1=mt_rand(100,255);
		$tmpC2=mt_rand(100,255);
		$buttum_c = ImageColorAllocate($image,$tmpC0,$tmpC1,$tmpC2);
		imagefill($image, 16, 13, $buttum_c);

		for ($i=0; $i<self::$length; $i++){
			$tmp =mb_substr(self::$code,$i,1, 'UTF-8');
			$array = array(-1,1);
			$p = array_rand($array);
			$an = $array[$p]*mt_rand(1,10);//角度
			$size = 24;
			imagettftext(
				$image,
				$size, 
				$an, 
				1+$i*$size, 
				35, 
				$text_c, 
				dirname(__FILE__) . DIRECTORY_SEPARATOR . self::$fontFace, 
				$tmp
			);
		}

		imagefill(self::$image, 16, 13, $buttum_c);
		for ( $i=0; $i< self::$width; $i++) {
			for ( $j=0; $j<self::$height; $j++) {
				$rgb = imagecolorat($image, $i , $j);
				if( (int)($i+10+sin($j/self::$height*2*M_PI)*10) <= self::$width && 
					(int)($i+10+sin($j/self::$height*2*M_PI)*10) >= 0 ) {
					imagesetpixel(self::$image, (int)($i+10+sin($j/self::$height*2*M_PI-M_PI*0.1)*4) , $j , $rgb);
				}
			} 
		}

		$rand = mt_rand(5,30);
		$rand1 = mt_rand(15,25);
		$rand2 = mt_rand(5,10);
		for ($yy=$rand; $yy<=+$rand+2; $yy++){
			for ($px=-80;$px<=80;$px=$px+0.1){
				$x=$px/$rand1;
				if ($x!=0){
					$y=sin($x);
				}
				$py=$y*$rand2;
				imagesetpixel(self::$image, $px+80, $py+$yy, $text_c);
			}
		}

	}


	public static function check($code, $sessionName='VerificationCode'){
		if (strtoupper($code)==$_SESSION[$sessionName]) {
			return true;
		}
		else
			return false;
	}
}